package http

import (
	"context"
	"encoding/base64"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"mall-portalv2/global"
	"mall-portalv2/internal/model"
	"mall-portalv2/internal/server/ctx"
	"mall-portalv2/library/common"
	"net/http"
	"time"
)

func OrderGeneratePayOrderHandlerFunc(c *gin.Context) {
	app := ctx.Gin{C: c}

	uidStr, isUid := c.Get("uid")
	if !isUid {
		global.Log.Error("uid不存在")
		app.Response(http.StatusInternalServerError, ctx.StatusInternalServerError, nil)
		return
	}
	UID := common.Str2Int64(fmt.Sprintf("%d", uidStr))

	type RequestBody struct {
		Num                 int64 `json:"num"`
		CrowdFundingId      int64 `json:"crowd_funding_id"`
		CrowdFundingThaliId int64 `json:"crowd_funding_thali_id"`
		ProductSkuId        int64 `json:"product_sku_id"`
		ProductId           int64 `json:"product_id"`

		FreightAmount float64 `json:"freightAmount"`                 // 运费金额
		SourceType    int64   `json:"sourceType" gorm:"source_type"` // 订单来源：0->PC订单；1->app订单
		BillType      int64   `json:"billType" gorm:"bill_type"`     // 发票类型：0->不开发票；1->电子发票；2->纸质发票
		Note          string  `json:"note" gorm:"note"`              // 订单备注
		ReceiverId    int64   `json:"receiverId"`
	}

	request := RequestBody{}
	if err := common.BindAndCheck(c, &request); err != nil {
		global.Log.Error("请求参数不正确", zap.Error(err))
		app.Response(http.StatusBadRequest, ctx.StatusBadRequest, err)
		return
	}

	global.Log.Info("映射完成", zap.Any("data", request))

	// 如果不填这个参数，默认为1
	if request.Num <= 0 {
		request.Num = 1
	}

	// 查询商品情况
	productAndCrowdFundingResult, err := svc.QueryProductAndCordFunding(c, request.CrowdFundingId, request.CrowdFundingThaliId, request.ProductSkuId, request.ProductId)
	if err != nil {
		global.Log.Error("mysql err", zap.Error(err))
		if err == gorm.ErrRecordNotFound {
			app.Response(http.StatusBadRequest, ctx.StatusBadRequest, "找不到对应的商品记录")
			return
		} else {
			app.Response(http.StatusInternalServerError, ctx.StatusInternalServerError, err)
			return
		}
	}

	global.Log.Info("查询完毕", zap.Any("data", productAndCrowdFundingResult))

	productSkuStock := productAndCrowdFundingResult.SkuStock - productAndCrowdFundingResult.SkuLockStock - request.Num
	crowdFuningSkuStock := productAndCrowdFundingResult.SkuStock - productAndCrowdFundingResult.SkuLockStock - request.Num

	// 库存查看
	if productSkuStock <= 0 || crowdFuningSkuStock <= 0 {
		app.Response(http.StatusOK, ctx.NO, "库存不足")
		return
	}

	// 查看众筹活动限购数量
	if productAndCrowdFundingResult.CftThaliLimitStatus == 1 {
		// TODO: 如果限购，判断一下 历史用户购买了多少个
		result, err := svc.QueryOmsOrderItemCountWhereUserIdAndProductId(c, productAndCrowdFundingResult.CrowdFundingThaliId, UID)
		if err != nil {
			global.Log.Error("mysql err", zap.Error(err))
			app.Response(http.StatusInternalServerError, ctx.StatusInternalServerError, err)
			return
		}
		var allNum int64
		global.Log.Info("历史购买记录为", zap.Any("result", len(result)))
		for _, item := range result {
			allNum = allNum + item.ProductQuantity
		}
		global.Log.Info("历史购买数量为", zap.Any("data", allNum))
		if productAndCrowdFundingResult.CftThaliLimit < (allNum + request.Num) {
			app.Response(http.StatusOK, ctx.NO, "购买数量超过了限购数量")
			return
		}
	}

	// TODO: 地址获取
	addressResult, err := svc.QueryUmsMemberReceiveAddressWhereID(context.Background(), request.ReceiverId)
	if err != nil {
		global.Log.Error("mysql err", zap.Error(err))
		if err == gorm.ErrRecordNotFound {
			app.Response(http.StatusBadRequest, ctx.StatusBadRequest, "找不到对应的地址记录")
			return
		} else {
			app.Response(http.StatusInternalServerError, ctx.StatusInternalServerError, err)
			return
		}
	}

	if addressResult.MemberId != UID {
		app.Response(http.StatusBadRequest, ctx.StatusBadRequest, errors.New("不是本人的地址"))
		return
	}

	// 查询用户情况
	userResult, err := svc.QueryUmsMemberWhereID(c, UID)
	if err != nil {
		global.Log.Error("mysql err", zap.Error(err))
		if err == gorm.ErrRecordNotFound {
			app.Response(http.StatusBadRequest, ctx.StatusBadRequest, "找不到对应的用户记录")
			return
		} else {
			app.Response(http.StatusInternalServerError, ctx.StatusInternalServerError, err)
			return
		}
	}

	// 查询订单设置
	orderSettingResult, err := svc.QueryOmsOrderSetting(c)
	if err != nil {
		global.Log.Error("mysql err", zap.Error(err))
		if err == gorm.ErrRecordNotFound {
			app.Response(http.StatusBadRequest, ctx.StatusBadRequest, "找不到对应的订单设置记录")
			return
		} else {
			app.Response(http.StatusInternalServerError, ctx.StatusInternalServerError, err)
			return
		}
	}

	//original_price
	originalPrice := productAndCrowdFundingResult.OriginalPrice
	// 优惠金额（打折打掉的费用）
	reduceAmount := (originalPrice - productAndCrowdFundingResult.CftThaliPrice) * float64(request.Num)
	// 应付金额
	PayAmount := productAndCrowdFundingResult.CftThaliPrice * float64(request.Num)

	// TODO: 写入数据库
	createDate := time.Now()
	DeadlinePayment := createDate.Add(time.Minute * time.Duration(orderSettingResult.NormalOrderOvertime))
	// TODO: 备注base64

	tempNote := base64.StdEncoding.EncodeToString([]byte(request.Note))

	insertModel := model.OmsOrder{
		MemberId:              UID,
		CouponId:              0,
		OrderSn:               "",
		CreateTime:            createDate,
		MemberUsername:        userResult.Username,
		TotalAmount:           PayAmount + request.FreightAmount,
		PayAmount:             PayAmount,
		FreightAmount:         request.FreightAmount,
		PromotionAmount:       reduceAmount,
		IntegrationAmount:     0,
		CouponAmount:          0,
		DiscountAmount:        0,
		SourceType:            request.SourceType,
		Status:                0,
		AutoConfirmDay:        orderSettingResult.ConfirmOvertime,
		Integration:           productAndCrowdFundingResult.GiftPoint,
		Growth:                productAndCrowdFundingResult.GiftGrowth,
		PromotionInfo:         productAndCrowdFundingResult.CfTitle,
		BillType:              request.BillType,
		BillHeader:            "",
		BillContent:           "",
		BillReceiverPhone:     "",
		BillReceiverEmail:     "",
		ReceiverID:            addressResult.ID,
		ReceiverName:          addressResult.Name,
		ReceiverPhone:         addressResult.PhoneNumber,
		ReceiverPostCode:      addressResult.PostCode,
		ReceiverProvince:      addressResult.Province,
		ReceiverCity:          addressResult.City,
		ReceiverRegion:        addressResult.Region,
		ReceiverDetailAddress: addressResult.DetailAddress,
		Note:                  tempNote,
		ConfirmStatus:         0,
		DeleteStatus:          0,
		UseIntegration:        0,
		//PaymentTime:           &zeroTime,
		DeliveryDate: &productAndCrowdFundingResult.CfDeliveryDate,
		//ReceiveTime:           &zeroTime,
		//CommentTime:           &zeroTime,
		//ModifyTime:            &zeroTime,
		DeadlinePayment: &DeadlinePayment,
	}

	insertModel.OrderSn = insertModel.GenerateOrderSn()

	orderResult, err := svc.CreateOrder(c, insertModel)
	if err != nil {
		global.Log.Error("mysql err", zap.Error(err))
		app.Response(http.StatusInternalServerError, ctx.StatusInternalServerError, err)
		return
	}

	global.Log.Info("id", zap.Any("id", orderResult.ID))

	insertModelItem := model.OmsOrderItem{
		OrderId:           orderResult.ID,
		MemberId:          UID,
		OrderSn:           insertModel.OrderSn,
		ProductId:         productAndCrowdFundingResult.ID,
		ProductPic:        productAndCrowdFundingResult.SkuPic,
		ProductName:       productAndCrowdFundingResult.Name,
		ProductBrand:      productAndCrowdFundingResult.Name,
		ProductSn:         productAndCrowdFundingResult.Name,
		ProductPrice:      productAndCrowdFundingResult.OriginalPrice,
		ProductQuantity:   request.Num,
		ProductSkuId:      productAndCrowdFundingResult.SkuID,
		ProductSkuCode:    productAndCrowdFundingResult.SkuSkuCode,
		ProductCategoryId: productAndCrowdFundingResult.ProductCategoryId,
		PromotionName:     "众筹活动",
		PromotionAmount:   reduceAmount,
		CouponAmount:      0,
		IntegrationAmount: 0,
		RealAmount:        productAndCrowdFundingResult.CftThaliPrice,
		GiftIntegration:   productAndCrowdFundingResult.GiftPoint,
		GiftGrowth:        productAndCrowdFundingResult.GiftGrowth,
		ProductAttr:       productAndCrowdFundingResult.SkuSpData,
		PromotionId:       productAndCrowdFundingResult.CrowdFundingId,
		PromotionSkuId:    productAndCrowdFundingResult.CrowdFundingThaliId,
	}

	orderItemResult, err := svc.CreateOrderItem(c, insertModelItem)
	if err != nil {
		global.Log.Error("mysql err", zap.Error(err))
		app.Response(http.StatusInternalServerError, ctx.StatusInternalServerError, err)
		return
	}

	global.Log.Info("id", zap.Any("id", orderItemResult.ID))

	// TODO: 锁库存
	if err := svc.LockOmsOrder(c, productAndCrowdFundingResult.SkuID, productAndCrowdFundingResult.SkuLockStock, productAndCrowdFundingResult.CftId, productAndCrowdFundingResult.CftLockThaliCount, request.Num); err != nil {
		global.Log.Error("mysql err", zap.Error(err))
		return
	}

	global.Log.Info("锁定库存")

	type SendData struct {
		OrderID             int64
		CrowdFundingId      int64 `json:"crowd_funding_id"`
		CrowdFundingThaliId int64 `json:"crowd_funding_thali_id"`
		ProductSkuId        int64 `json:"product_sku_id"`
		ProductId           int64 `json:"product_id"`
		Product             model.ViewProductCrowdFundingDetail
		Num                 int64 `json:"num"`
	}

	sendData := SendData{
		OrderID:             orderResult.ID,
		CrowdFundingId:      request.CrowdFundingId,
		CrowdFundingThaliId: request.CrowdFundingThaliId,
		ProductSkuId:        request.ProductSkuId,
		ProductId:           request.ProductId,
		Product:             productAndCrowdFundingResult,
		Num:                 request.Num,
	}

	// TODO: 推入mq
	//var tempTime = 1000 * 60 * orderSettingResult.NormalOrderOvertime
	var tempTime = orderSettingResult.NormalOrderOvertime * 60 * 1000
	if err := svc.SendRabbitMqMessage("mall.order.ttl", sendData, tempTime); err != nil {
		//if err := svc.SendRabbitMqMessage("mall.order.ttl", sendData, 1000*10); err != nil {
		global.Log.Error("mq err", zap.Error(err))
		app.Response(http.StatusInternalServerError, ctx.StatusInternalServerError, err)
		return
	}

	global.Log.Info("推入mq成功", zap.Any("倒计时", tempTime))

	app.Response(http.StatusOK, ctx.OK, orderResult)
}
